// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DataViewDs.cs" company="SmartPlan">
//   SmartPlan 2011
// </copyright>
// <summary>
//   The data view ds.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace DbDiff.Common.DataAccess
{
    using System;
    using System.Collections;
    using System.Data;

    /// <summary>
    /// The data view ds.
    /// </summary>
    public class DataViewDs
    {
        #region public values

        /// <summary>
        /// The keys type.
        /// </summary>
        public enum KeysType
        {
            /// <summary>
            ///   The primary.
            /// </summary>
            Primary, 

            /// <summary>
            ///   The name.
            /// </summary>
            Name, 

            /// <summary>
            ///   The index name.
            /// </summary>
            IndexName, 

            /// <summary>
            ///   The foreign name.
            /// </summary>
            ForeignName
        }

        /// <summary>
        ///   The this.
        /// </summary>
        /// <param name = "index">
        ///   The index.
        /// </param>
        public DataRowView this[int index]
        {
            get { return this.dv[index]; }
        }

        /// <summary>
        ///   Gets Lengt.
        /// </summary>
        public int Lengt { get; private set; }

        /// <summary>
        ///   Gets or sets NewRowFilter.
        /// </summary>
        public string NewRowFilter { get; set; }

        /// <summary>
        ///   Gets NewSort.
        /// </summary>
        public string NewSort { get; private set; }

        #endregion public values

        #region private values

        /// <summary>
        ///   The dv.
        /// </summary>
        private readonly DataView dv;

        /// <summary>
        ///   The keys name.
        /// </summary>
        private string[] keysName;

        /// <summary>
        ///   The keys ordinal.
        /// </summary>
        private int[] keysOrdinal;

        /// <summary>
        ///   The sorter.
        /// </summary>
        private IComparer sorter;

        /// <summary>
        ///   Gets BaseSort.
        /// </summary>
        private string BaseSort
        {
            get { return this.dv.Sort; }
        }

        #endregion private values

        #region primarykeys string

        /// <summary>
        /// genereate primarykey string
        /// </summary>
        /// <param name="tbl">
        /// </param>
        /// <param name="type">
        /// </param>
        /// <returns>
        /// The key names.
        /// </returns>
        private static string KeyNames(DataTable tbl, KeysType type)
        {
            string ret = string.Empty;
            int max = tbl.PrimaryKey.Length;

            switch (type)
            {
                case KeysType.Name:
                    max = 2;
                    break;
                case KeysType.Primary:
                    max = tbl.PrimaryKey.Length;
                    break;
                case KeysType.IndexName:
                    max = tbl.PrimaryKey.Length - 1;
                    break;
                case KeysType.ForeignName:
                    max = tbl.PrimaryKey.Length - 1;
                    break;
            }

            for (int i = 0; i < max; i++)
            {
                ret += string.Format("{0},", tbl.PrimaryKey[i].ColumnName);
            }

            return ret.Substring(0, ret.Length - 1);
        }

        #endregion primarykeystring

        #region constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="DataViewDs"/> class.
        /// </summary>
        /// <param name="tbl">
        /// The tbl.
        /// </param>
        /// <param name="rowFilter">
        /// The row filter.
        /// </param>
        /// <param name="type">
        /// The type.
        /// </param>
        public DataViewDs(DataTable tbl, string rowFilter, KeysType type)
        {
            this.NewSort = string.Empty;
            this.InitKeys(tbl, type);
            this.dv = new DataView(tbl, rowFilter, this.NewSort, DataViewRowState.CurrentRows);

            this.NewRowFilter = rowFilter;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DataViewDs"/> class.
        /// </summary>
        /// <param name="tbl">
        /// The tbl.
        /// </param>
        /// <param name="rowFilter">
        /// The row filter.
        /// </param>
        /// <param name="rowState">
        /// The row state.
        /// </param>
        /// <param name="type">
        /// The type.
        /// </param>
        public DataViewDs(DataTable tbl, string rowFilter, DataViewRowState rowState, KeysType type)
        {
            this.NewSort = string.Empty;
            this.InitKeys(tbl, type);
            this.dv = new DataView(tbl, rowFilter, this.NewSort, rowState);

            this.NewRowFilter = rowFilter;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DataViewDs"/> class.
        /// </summary>
        /// <param name="dv">
        /// The dv.
        /// </param>
        /// <param name="rowFilter">
        /// The row filter.
        /// </param>
        public DataViewDs(DataView dv, string rowFilter)
        {
            this.NewSort = string.Empty;
            this.dv = dv;
            this.NewRowFilter = rowFilter;
            this.InitKeys(dv.Table, KeysType.Primary);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DataViewDs"/> class.
        /// </summary>
        /// <param name="dvDs">
        /// The dv ds.
        /// </param>
        /// <param name="rowFilter">
        /// The row filter.
        /// </param>
        public DataViewDs(DataViewDs dvDs, string rowFilter)
        {
            this.NewSort = string.Empty;
            KeysType type = KeysType.Name;
            this.dv = dvDs.dv;
            this.NewRowFilter = rowFilter;

            if (this.BaseSort.Split(',').Length == this.dv.Table.PrimaryKey.Length)
            {
                type = KeysType.Primary;
            }

            this.InitKeys(this.dv.Table, type);
        }

        #endregion constructor

        #region init

        /// <summary>
        /// The init keys.
        /// </summary>
        /// <param name="tbl">
        /// The tbl.
        /// </param>
        /// <param name="type">
        /// The type.
        /// </param>
        private void InitKeys(DataTable tbl, KeysType type)
        {
            switch (tbl.GetType().Name)
            {
                case "tblForeignKeyRow":
                    this.sorter = new SortForeignKeyByKeyNo();
                    break;
                case "tblIndexKeyRow": 
                    // DbObjectsDs.IndexKeyRow
                    this.sorter = new SortIndexKeyByKeyNo();
                    break;
                case "tblFieldsRow":
                    this.sorter = new SortFieldRowByColId();
                    break;
                case "tblCheckRow":
                    this.sorter = new SortCheckById();
                    break;
                default:
                    this.sorter = null;
                    break;
            }

            this.NewSort = KeyNames(tbl, type);

            this.keysName = this.NewSort.Split(',');
            this.Lengt = this.keysName.Length;
            this.keysOrdinal = new int[this.Lengt];

            for (int i = 0; i < this.Lengt; i++)
            {
                this.keysOrdinal[i] = tbl.Columns[this.keysName[i]].Ordinal;
            }
        }

        #endregion init

        /// <summary>
        /// The find rows.
        /// </summary>
        /// <param name="obj">
        /// The obj.
        /// </param>
        /// <param name="isSort">
        /// The is sort.
        /// </param>
        /// <returns>
        /// </returns>
        public DataRowView[] FindRows(object[] obj, bool isSort)
        {
            var rowFilter = this.dv.RowFilter;
            if (rowFilter != null && rowFilter != this.NewRowFilter)
            {
                this.dv.RowFilter = this.NewRowFilter;
            }

            DataRowView[] d = this.dv.FindRows(obj);

            if (isSort & this.sorter != null)
            {
                Array.Sort(d, 0, d.Length, this.sorter);
            }

            return d;
        }

        /// <summary>
        /// The find rows.
        /// </summary>
        /// <param name="obj">
        /// The obj.
        /// </param>
        /// <param name="sorter">
        /// The sorter.
        /// </param>
        /// <returns>
        /// </returns>
        public DataRowView[] FindRows(object[] obj, IComparer sorter)
        {
            if (this.dv.RowFilter != this.NewRowFilter)
            {
                this.dv.RowFilter = this.NewRowFilter;
            }

            DataRowView[] d = this.dv.FindRows(obj);

            if (sorter != null)
            {
                Array.Sort(d, 0, d.Length, sorter);
            }

            return d;
        }


        /// <summary>
        /// The find.
        /// </summary>
        /// <param name="obj">
        /// The obj.
        /// </param>
        /// <returns>
        /// The find.
        /// </returns>
        public int Find(object[] obj)
        {
            var dataView = this.dv;
            if (dataView != null && dataView.RowFilter != this.NewRowFilter)
            {
                this.dv.RowFilter = this.NewRowFilter;
            }

            return this.dv.Find(obj);
        }

        /// <summary>
        /// GetKeysName
        /// </summary>
        /// <returns>
        /// </returns>
        public string[] GetKeysName()
        {
            return this.keysName;
        }

        /// <summary>
        /// GetKeysValue
        /// </summary>
        /// <param name="row">
        /// </param>
        /// <returns>
        /// </returns>
        public object[] GetRowKeysValue(DataRow row)
        {
            var obj = new object[this.Lengt];
            for (int i = 0; i < this.Lengt; i++)
            {
                obj[i] = row.ItemArray[this.keysOrdinal[i]];
            }

            return obj;
        }

        /// <summary>
        /// The dispose.
        /// </summary>
        public void Dispose()
        {
            this.dv.Dispose();
        }
    }
}